/* 
 * cms，一个基于J2EE架构内容管理系统
 * Copyright © GrayRabbit Co., Ltd. All rights reserved.
 * Department:运营department
 * 更多信息请访问：
 * http://code.google.com/p/gray-rabbit-cms/
 */
package org.grayrabbit.cms.service.system.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.grayrabbit.cms.dao.system.AdminDao;
import org.grayrabbit.cms.dao.system.AdminOperRelaDao;
import org.grayrabbit.cms.entity.Admin;
import org.grayrabbit.cms.entity.AdminOperRela;
import org.grayrabbit.cms.service.category.impl.CategoryCache;
import org.grayrabbit.cms.service.system.AdminOperRelaService;
import org.grayrabbit.cms.util.OperCodeJSONUtil;
import org.grayrabbit.cms.vo.system.AdminOperRelaBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.grayrabbit.dao.util.Page;
import org.grayrabbit.service.impl.GenericServiceImpl;
/**
 * <b>AdminOperRela</b>的service实现类，事务加此处：





 * @version 1.0,创建时间: 2011-05-16 15:55:12  
 */
@Service
@Transactional
public class AdminOperRelaServiceImpl extends GenericServiceImpl implements AdminOperRelaService {
	/**
	 * 注入dao层：
	 */
	@Autowired
	@Qualifier("adminOperRelaDaoImpl")
	private AdminOperRelaDao adminOperRelaDao;
	
	@Autowired
	@Qualifier("adminDaoImpl")
	private AdminDao adminDao;
	
	/**
	 * 此方法执行时为只读事务：
	 * @see AdminOperRelaService#getAdminOperRela(String)
	 */
	@Transactional(readOnly=true)
	public AdminOperRela getAdminOperRela(final String adminOperRelaId){
		AdminOperRela adminOperRela = adminOperRelaDao.findById(adminOperRelaId);
		adminOperRelaDao.initialize(adminOperRela);
		return adminOperRela;
	}
	
	/**
	 * @see AdminOperRelaService#delete(String)
	 */
	@Transactional
	public void delete(final AdminOperRela adminOperRela) {
		adminOperRelaDao.makeTransient(adminOperRela);
	}
	
	/**
	 * @see AdminOperRelaService#save(adminOperRela)
	 */
	@Transactional
	public void save(final AdminOperRela adminOperRela) {
		adminOperRelaDao.makePersistent(adminOperRela);		
	}
	
	/**
	 * 此方法执行时为只读事务：
	 * @see AdminOperRelaService#getPage(AdminOperRelaBean)
	 */
	@Transactional(readOnly=true)
	public Page<AdminOperRela> getPage(final AdminOperRelaBean adminOperRelaBean){
		Page<AdminOperRela> page =  new Page<AdminOperRela>();
		page.setTotal(adminOperRelaDao.count(adminOperRelaBean));
		page.setResult(adminOperRelaDao.findByQc(adminOperRelaDao.assembly(adminOperRelaBean)));
		return page;
	}

	/**
	 * 此方法执行时为只读事务：
	 * @see AdminOperRelaService#list(Page, AdminOperRelaBean)
	 */
	public void list(Page<AdminOperRela> page, AdminOperRelaBean adminOperRelaBean) {
		if(page==null)
			return;
		if(page.isAutoCount()){
			page.setTotal(adminOperRelaDao.count(adminOperRelaBean));
		}
		page.setResult(adminOperRelaDao.findByPage(page,adminOperRelaBean));
	}
	
	/**
	 * 根据主键id列删除，批量删除AdminOperRela
	 * @see AdminOperRelaService#delete(String[])
	 */
	public void delete(final String[] key) {
		int i =0;
		for(String id : key){
			adminOperRelaDao.makeTransient(adminOperRelaDao.findById(id));
			i++;
			if(i==MAX_CLEAR)
				adminOperRelaDao.clear();
		}
		
	}
	@Transactional
	public void save(List<AdminOperRela> relaList) {
		 for(AdminOperRela rela:relaList){
			 adminOperRelaDao.makePersistent(rela);
			 
		 } 
	}

	@Transactional(readOnly=true)
	public List<AdminOperRela> findAllAuthCodeByAdminId(String adminId) {
		List<AdminOperRela> list = adminOperRelaDao.findAllAuthCodeByAdminId(adminId);
		if(list != null && !list.isEmpty()){
			for(AdminOperRela r :list){
				adminOperRelaDao.initialize(r.getOperCode());
			}
		} 
		return list;
	}
	
	@Transactional(readOnly=true)
	public  String wrapAuthJsonText(String objectId){
		List<AdminOperRela> list = findAllAuthCodeByAdminId(objectId);
		return OperCodeJSONUtil.fromAdminOperRelaToJSON(list);
	}
	

	@Transactional
	public void saveAllAuthCodeByAdminId(String adminId,String objectType ,String authJsonText) {
		List<AdminOperRela> list = OperCodeJSONUtil.getAdminAuth(authJsonText, adminId, objectType);
		AdminContext.remove(adminDao.findById(adminId).getLoginName());//清除用户缓存
		makeTransientAdminAuth(adminId);
		save(list);
		CategoryCache.removeAuthCatsAndFlagbyAdminIds(adminId);
	}

	/**
	 * 权限删除   
	 * @param targetId   站点 、 栏目 、专题
	 * @param targetType  （targetId  类型）
	 */
	@Transactional
	public void deleteObjectAuth(String[] targetIds, String targetType) {
		if(targetIds == null || ArrayUtils.isEmpty(targetIds) || StringUtils.isBlank(targetType)) 
		   throw new IllegalArgumentException(" targetIds or targetType   can't be  blank or empty!");
		for(String targetId :targetIds ){			
			List<AdminOperRela>  list = adminOperRelaDao.findObjectAuth(targetId, targetType);	
			for(AdminOperRela r:list){
				String ids = OperCodeJSONUtil.delteTargetIds(r.getOperTargetId(), targetId);
				String ids2 = OperCodeJSONUtil.delteTargetIds(r.getOperTargetId2(), targetId);
				String ids3 = OperCodeJSONUtil.delteTargetIds(r.getOperTargetId3(), targetId);
				String ids4 = OperCodeJSONUtil.delteTargetIds(r.getOperTargetId4(), targetId);
				String ids5 = OperCodeJSONUtil.delteTargetIds(r.getOperTargetId5(), targetId);
				if(StringUtils.isBlank(ids) && StringUtils.isBlank(ids2) && StringUtils.isBlank(ids3)
						&& StringUtils.isBlank(ids4) && StringUtils.isBlank(ids5)){
					adminOperRelaDao.makeTransient(r);	
				}else{
					r.setOperTargetId(ids);
					r.setOperTargetId2(ids2);
					r.setOperTargetId3(ids3);
					r.setOperTargetId4(ids4);
					r.setOperTargetId5(ids5);
					adminOperRelaDao.makePersistent(r);
				} 
				AdminContext.remove(r.getAdmin().getLoginName());//清除用户缓存
			}
		}
	}
	
	
	/**
	 * 删除  管理员  时 删除权限
	 */
	@Transactional
	public void deleteAdminAuth(String adminId) {
		AdminContext.remove(adminDao.findById(adminId).getLoginName());//清除用户缓存
		CategoryCache.removeAuthCatsAndFlagbyAdminIds(adminId);
		makeTransientAdminAuth(adminId);
	}
	/**
	 *  删除管理员权限
	 */
	private void makeTransientAdminAuth(String adminId){
		if(StringUtils.isBlank(adminId) ) 
			   throw new IllegalArgumentException("adminId  can't be  blank!");
		List<AdminOperRela> relas = adminOperRelaDao.findAllAuthCodeByAdminId(adminId);
		for(AdminOperRela r:relas){
			adminOperRelaDao.makeTransient(r);
		}
	}


	/**
	 * @author cwd
	 * 根据admin的loginname判断是否包含admin
	 * @param adminList
	 * @param admin
	 * @return
	 */
	public boolean contain(List<Admin> adminList,Admin admin){
		if(admin == null){
			return false;
		}
		for(Admin admintemp:adminList){
			if(admintemp.getLoginName().equals(admin.getLoginName())){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * @author cwd
	 * 根据admin的ID删除admin
	 * @param newAdmin
	 * @param admin
	 */
	private void removeAdmin(List<Admin> newAdmin, Admin admin) {
		if(newAdmin == null){
			return;
		}
		int length = newAdmin.size();
		for(int i=0;i<length;i++){
			if(newAdmin.get(i).getAdminId().equals(admin.getAdminId())){
				newAdmin.remove(i);
				return;
			}
		}
	}

	/**
	 * @author cwd
	 * 增加用户的权限
	 * @param admin
	 * @param rel
	 */
	private void addPower(Admin admin, AdminOperRela rel) {
		List<AdminOperRela> rs =adminOperRelaDao.findByTargetIdAndOperCodeId(admin.getAdminId(),
				rel.getOperCode().getOperId(),null);
		AdminOperRela re = new AdminOperRela();
		re.setAdmin(admin);
		re.setOperCode(rel.getOperCode());
		re.setOperTargetType(rel.getOperTargetType());
		re.setOperTargetId(rel.getOperTargetId());
		String id  = re.getOperTargetId();
		Set<Object>  set = new HashSet<Object>();
		set.add(id);
		if(rs != null && !rs.isEmpty()){
			//如果已有记录则添加到原来的其他权限
			for(AdminOperRela rela:rs){ 
				//把数据库里的权限都加到set去
				OperCodeJSONUtil.addObjectAuth(rela.getOperTargetId(), 
						rela.getOperTargetId2(),rela.getOperTargetId3(), 
						rela.getOperTargetId4(), rela.getOperTargetId5(),set); 
				//删除cms_admin_oper_rela这个表中相应整条记录
				adminOperRelaDao.makeTransient(rela);
			}
			//把set保存
		}
		// 数据库还没有这条记录的时候
		String ids = OperCodeJSONUtil.join(set, "-");
		List<String> list = OperCodeJSONUtil.splitTargetIds(ids);
		if (list.size() > 0)
			re.setOperTargetId(list.get(0));
		if (list.size() > 1)
			re.setOperTargetId2(list.get(1));
		if (list.size() > 2)
			re.setOperTargetId3(list.get(2));
		if (list.size() > 3)
			re.setOperTargetId4(list.get(3));
		if (list.size() > 4)
			re.setOperTargetId5(list.get(4));
		adminOperRelaDao.makePersistent(re);
	}

	/**
	 * @author cwd
	 * 删除用户相关权限
	 * @param admin
	 * @param rel
	 */
	private void deletePower(Admin admin, AdminOperRela rel) {
		List<AdminOperRela> rs =adminOperRelaDao.findByTargetIdAndOperCodeId(admin.getAdminId(),
				rel.getOperCode().getOperId(),null);
		if(rs != null && !rs.isEmpty()){
			AdminOperRela re = new AdminOperRela();
			re.setAdmin(admin);
			re.setOperCode(rel.getOperCode());
			re.setOperTargetType(rel.getOperTargetType());
			re.setOperTargetId(rel.getOperTargetId());
			String id  = re.getOperTargetId();
			Set<Object>  set = new HashSet<Object>();
			for(AdminOperRela rela:rs){ 
				//把数据库里的权限都加到set去
				OperCodeJSONUtil.addObjectAuth(rela.getOperTargetId(), 
						rela.getOperTargetId2(),rela.getOperTargetId3(), 
						rela.getOperTargetId4(), rela.getOperTargetId5(),set); 
				//删除cms_admin_oper_rela这个表中相应整条记录
				adminOperRelaDao.makeTransient(rela);
			}
			set.remove(id);
			if(set.isEmpty()){
				//如果set为空，就不保存
			}else{
				//把set保存
				String ids = OperCodeJSONUtil.join(set, "-");
				List<String> list = OperCodeJSONUtil.splitTargetIds(ids);
				if(list.size()>0) re.setOperTargetId(list.get(0));
				if(list.size()>1) re.setOperTargetId2(list.get(1));
				if(list.size()>2) re.setOperTargetId3(list.get(2));
				if(list.size()>3) re.setOperTargetId4(list.get(3));
				if(list.size()>4) re.setOperTargetId5(list.get(4));		
				adminOperRelaDao.makePersistent(re);	
			}
	   }
	}

	/**
	 * @author cwd
	 * 权限的管理
	 */
	public void distributeAuditAuthCode(AdminOperRela rel,
			String auditNames) {
		//新来的需要给权限的列表
		List<Admin> newAdmin = adminDao.getAdminsBynames(auditNames) ;
		//数据库原有的权限列表
		List<Admin> oldAdmin =adminOperRelaDao.findCategoryAuditorsAdmin(rel.getOperCode().getOperId(), rel.getOperTargetId());
		//循环数据库，如果新来的权限在老的中有，就数据不做改变，因为新的处理了一个用户，所有移除掉该用户
		//老的中没有，就得增加该用户的相关权限
		for(Admin admin:oldAdmin){
			if(contain(newAdmin, admin)){
				removeAdmin(newAdmin,admin);
			}else{
				deletePower(admin,rel);
			}
		}
		//剩下来未处理的就是新的用户需要新的权限，给他们加相应权限
		for(Admin admin:newAdmin){
			addPower(admin,rel);
		}
	}
	
	



	public void addObjectDistributeAuthCode( AdminOperRela re) {
		List<AdminOperRela> rs =adminOperRelaDao.findByTargetIdAndOperCodeId(
				re.getAdmin().getAdminId(), re.getOperCode().getOperId(), null);
		if(rs != null && !rs.isEmpty()){			
			String id  = re.getOperTargetId();
			Set<Object>  set = new HashSet<Object>();
			set.add(id);
			for(AdminOperRela rela:rs){ 
				OperCodeJSONUtil.addObjectAuth(rela.getOperTargetId(), 
						rela.getOperTargetId2(),rela.getOperTargetId3(), 
						rela.getOperTargetId4(), rela.getOperTargetId5(),set); 
				adminOperRelaDao.makeTransient(rela);
			} 
			String ids = OperCodeJSONUtil.join(set, "-");
			List<String> list = OperCodeJSONUtil.splitTargetIds(ids);
			if(list.size()>0) re.setOperTargetId(list.get(0));
			if(list.size()>1) re.setOperTargetId2(list.get(1));
			if(list.size()>2) re.setOperTargetId3(list.get(2));
			if(list.size()>3) re.setOperTargetId4(list.get(3));
			if(list.size()>4) re.setOperTargetId5(list.get(4));			
		} 
		adminOperRelaDao.makePersistent(re);
	}

 
}